package com.ibeeking.found.org.cp.rest.service.impl;

import cn.hutool.core.collection.CollUtil;
import com.ibeeking.found.common.entity.AreaDTO;
import com.ibeeking.found.common.enums.DefaultEnum;
import com.ibeeking.found.common.utils.DataUtils;
import com.ibeeking.found.common.utils.UserUtils;

import com.ibeeking.gmc.global.api.feign.GlobalDictFeignClient;
import com.ibeeking.found.org.api.common.dto.EmployeeAddressDTO;
import com.ibeeking.found.org.cp.rest.service.IEmployeeAddressService;
import com.ibeeking.found.org.cp.rest.service.IEmployeeService;
import com.ibeeking.found.org.service.common.bo.EmployeeAddressBO;
import com.ibeeking.found.org.service.common.dos.EmployeeAddressDO;
import com.ibeeking.found.org.service.common.enums.HasDefaultEnum;
import com.ibeeking.found.org.service.common.param.EmployeeAddressParam;
import com.ibeeking.found.org.service.common.vo.AreaVO;
import com.ibeeking.found.org.service.common.vo.EmployeeAddressListVO;
import com.ibeeking.found.org.service.common.vo.EmployeeAddressVO;
import com.ibeeking.found.org.service.mapper.EmployeeAddressMapper;
import com.ibeeking.nematos.core.utils.SpringBeanUtil;
import com.ibeeking.nematos.exception.BusinessException;
import com.ibeeking.nematos.utils.bean.BeanUtil;
import com.ibeeking.nematos.utils.data.Collections3;
import com.ibeeking.nematos.utils.json.JsonUtils;
import com.ibeeking.nematos.utils.result.ResponseResult;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @ClassName EmployeeAddressServiceImpl
 * @Description
 * @Author ibeeking
 * @Date 2021-01-27 18:50
 **/
@Service
public class EmployeeAddressServiceImpl extends ServiceImpl<EmployeeAddressMapper, EmployeeAddressDO> implements IEmployeeAddressService {

    @Resource
    private IEmployeeAddressService receAddrServiceImpl;

    @Resource
    private EmployeeAddressMapper employeeAddressMapper;

    @Resource
    private GlobalDictFeignClient globalDictFeignClient;

    @Resource
    private IEmployeeService employeeServiceImpl;

    @Override
    public EmployeeAddressBO selById(Long id) {
        if (id == null) {
            return null;
        }
        EmployeeAddressDO entityDO = employeeAddressMapper.selectById(id);
        return BeanUtil.convertBean(entityDO, EmployeeAddressBO.class);

    }

    @Override
    public List<EmployeeAddressListVO> list(Long memberId) {
        if (memberId == null) {
            return Collections3.emptyList();
        }
        //根据默认地址排在第一个,且按创建时间倒排
        List<EmployeeAddressDO> list = employeeAddressMapper.selectList(new LambdaQueryWrapper<EmployeeAddressDO>().eq(EmployeeAddressDO::getEmployeeId, memberId).orderByDesc(EmployeeAddressDO::getHasDefault).orderByDesc(EmployeeAddressDO::getCreateTime));
        List<EmployeeAddressListVO> receAddrDos = JsonUtils.jsonToList(list, EmployeeAddressListVO.class);
        //获取完整收货地址
        if (Collections3.isNotEmpty(receAddrDos)) {
            Set<String> codeSet = new HashSet<>();
            receAddrDos.forEach(x -> {
                codeSet.add(x.getProvinceCode());
                codeSet.add(x.getCityCode());
                codeSet.add(x.getRegionCode());
                codeSet.add(x.getStreetCode());
            });
            List<AreaDTO> areaDtos = Optional.ofNullable(globalDictFeignClient.queryNames(new ArrayList<>(codeSet))).map(ResponseResult::getData).orElseGet(() -> Collections.EMPTY_LIST);
            Map<String, String> areaMap = areaDtos.stream().collect(Collectors.toMap(AreaDTO::getCode, AreaDTO::getName, (o, n) -> n));
            receAddrDos.forEach(x -> {
                x.setFullAddr(DataUtils.strSplicing(areaMap.get(x.getProvinceCode()), areaMap.get(x.getCityCode()), areaMap.get(x.getRegionCode()), areaMap.get(x.getStreetCode()), x.getDetailAddress()));
                x.setHidePhone(DataUtils.hidePhone(x.getPhone()));
            });
        }
        return receAddrDos;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean add(EmployeeAddressParam param) {
        Long memberId = UserUtils.getUserId();
        EmployeeAddressDO entityDO = BeanUtil.convertBean(param, EmployeeAddressDO.class);
        if (DefaultEnum.YES.getValue().equals(entityDO.getHasDefault())) {
            //当前添加项设为默认时,先把老的默认改为非默认
            receAddrServiceImpl.modifyOldDefaultYesToNo(memberId);
        }
        entityDO.setEmployeeId(memberId);
        entityDO.setCreateBy(memberId);
        employeeAddressMapper.insert(entityDO);
        //修改会员信息中的地址
        EmployeeAddressDO EmployeeAddressDODefault = getBean().selectDefaultOrFirstAddr(memberId);
        if (EmployeeAddressDODefault != null) {
            employeeServiceImpl.modifyAddr(memberId, EmployeeAddressDODefault.getProvinceCode(), EmployeeAddressDODefault.getCityCode(), EmployeeAddressDODefault.getRegionCode(), EmployeeAddressDODefault.getStreetCode(), EmployeeAddressDODefault.getDetailAddress());
        }
        return true;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean modify(EmployeeAddressParam param) {
        Long memberId = UserUtils.getUserId();
        EmployeeAddressDO entityDO = BeanUtil.convertBean(param, EmployeeAddressDO.class);
        if (DefaultEnum.YES.getValue().equals(entityDO.getHasDefault())) {
            //当前添加项设为默认时,先把老的默认改为非默认
            receAddrServiceImpl.modifyOldDefaultYesToNo(memberId);
        }
        entityDO.setEmployeeId(memberId);
        entityDO.setModifyBy(memberId);
        if (param.getPhone().contains("*")) {
            param.setPhone(null);
        }
        employeeAddressMapper.updateById(entityDO);
        //修改会员信息中的地址
        EmployeeAddressDO EmployeeAddressDODefault = getBean().selectDefaultOrFirstAddr(memberId);
        if (EmployeeAddressDODefault != null) {
            employeeServiceImpl.modifyAddr(memberId, EmployeeAddressDODefault.getProvinceCode(), EmployeeAddressDODefault.getCityCode(), EmployeeAddressDODefault.getRegionCode(), EmployeeAddressDODefault.getStreetCode(), EmployeeAddressDODefault.getDetailAddress());
        }
        return true;
    }

    @Override
    public EmployeeAddressVO view(Long id) {
        EmployeeAddressBO EmployeeAddressBO = getBean().selById(id);
        if (EmployeeAddressBO == null) {
            return null;
        }
        EmployeeAddressVO EmployeeAddressVO = BeanUtil.convertBean(EmployeeAddressBO, EmployeeAddressVO.class);
        EmployeeAddressVO.setHidePhone(DataUtils.hidePhone(EmployeeAddressVO.getPhone()));
        //所在地区
        List<String> codeList = new ArrayList<>();
        codeList.add(EmployeeAddressVO.getProvinceCode());
        codeList.add(EmployeeAddressVO.getCityCode());
        codeList.add(EmployeeAddressVO.getRegionCode());
        codeList.add(EmployeeAddressVO.getStreetCode());
        List<AreaDTO> areaDtos = Optional.ofNullable(globalDictFeignClient.queryNames(codeList)).map(ResponseResult::getData).orElseGet(() -> Collections.EMPTY_LIST);
        EmployeeAddressVO.setAreas(JsonUtils.jsonToList(areaDtos, AreaVO.class));
        return EmployeeAddressVO;
    }

    @Override
    public EmployeeAddressDTO feignView(Long id) {
        EmployeeAddressBO entityBO = getBean().selById(id);
        if (entityBO == null) {
            return null;
        }
        EmployeeAddressDTO dto = BeanUtil.convertBean(entityBO, EmployeeAddressDTO.class);
        //获取完整收货地址
        if (dto != null) {
            List<String> codeList = CollUtil.newArrayList();
            codeList.add(dto.getProvinceCode());
            codeList.add(dto.getCityCode());
            codeList.add(dto.getRegionCode());
            codeList.add(dto.getStreetCode());
            List<AreaDTO> areaDtos = Optional.ofNullable(globalDictFeignClient.queryNames(codeList)).map(ResponseResult::getData).orElseGet(() -> Collections.EMPTY_LIST);
            Map<String, String> areaMap = areaDtos.stream().collect(Collectors.toMap(AreaDTO::getCode, AreaDTO::getName, (o, n) -> n));
            dto.setProvinceName(areaMap.get(dto.getProvinceCode()));
            dto.setCityName(areaMap.get(dto.getCityCode()));
            dto.setRegionName(areaMap.get(dto.getRegionCode()));
            dto.setStreetName(areaMap.get(dto.getStreetCode()));
        }
        return dto;
    }

    @Override
    public EmployeeAddressDTO feignViewDefault(Long memberId) {
        if (memberId == null) {
            return null;
        }

        LambdaQueryWrapper<EmployeeAddressDO> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(EmployeeAddressDO::getEmployeeId, memberId);
        wrapper.eq(EmployeeAddressDO::getHasDefault, HasDefaultEnum.YES.getValue());
        List<EmployeeAddressDO> dos = employeeAddressMapper.selectList(wrapper);
        if (Collections3.isEmpty(dos)) {
            return null;
        }
        EmployeeAddressBO entityBO = BeanUtil.convertBean(dos.get(0), EmployeeAddressBO.class);
        if (entityBO == null) {
            return null;
        }
        EmployeeAddressDTO dto = BeanUtil.convertBean(entityBO, EmployeeAddressDTO.class);
        //获取完整收货地址
        if (dto != null) {
            List<String> codeList = CollUtil.newArrayList();
            codeList.add(dto.getProvinceCode());
            codeList.add(dto.getCityCode());
            codeList.add(dto.getRegionCode());
            codeList.add(dto.getStreetCode());
            List<AreaDTO> areaDtos = Optional.ofNullable(globalDictFeignClient.queryNames(codeList)).map(ResponseResult::getData).orElseGet(() -> Collections.EMPTY_LIST);
            Map<String, String> areaMap = areaDtos.stream().collect(Collectors.toMap(AreaDTO::getCode, AreaDTO::getName, (o, n) -> n));
            dto.setProvinceName(areaMap.get(dto.getProvinceCode()));
            dto.setCityName(areaMap.get(dto.getCityCode()));
            dto.setRegionName(areaMap.get(dto.getRegionCode()));
            dto.setStreetName(areaMap.get(dto.getStreetCode()));
        }
        return dto;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean del(Long id) {
        return employeeAddressMapper.deleteById(id) > 0;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean modifyOldDefaultYesToNo(Long memberId) {
        if (memberId == null) {
            throw BusinessException.create("修改默认收货地址失败(会员id不能为空)!");
        }
        //把会员的老的默认地址改为非默认(默认地址只能有一个)
        LambdaUpdateWrapper<EmployeeAddressDO> updateWrapper = new LambdaUpdateWrapper<EmployeeAddressDO>().eq(EmployeeAddressDO::getEmployeeId, memberId).eq(EmployeeAddressDO::getHasDefault, DefaultEnum.YES.getValue());
        EmployeeAddressDO up = new EmployeeAddressDO();
        up.setHasDefault(DefaultEnum.NO.getValue());
        return employeeAddressMapper.update(up, updateWrapper) > 0;
    }


    @Transactional(rollbackFor = Exception.class, isolation = Isolation.READ_UNCOMMITTED)
    @Override
    public EmployeeAddressDO selectDefaultOrFirstAddr(Long memberId) {
        EmployeeAddressDO entityDO = employeeAddressMapper.selectOne(new LambdaQueryWrapper<EmployeeAddressDO>().eq(EmployeeAddressDO::getHasDefault, 1).eq(EmployeeAddressDO::getEmployeeId, memberId));
        if (entityDO == null) {
            entityDO = employeeAddressMapper.selectOne(new LambdaQueryWrapper<EmployeeAddressDO>().eq(EmployeeAddressDO::getEmployeeId, memberId).orderByDesc(EmployeeAddressDO::getCreateTime).last("limit 1"));
        }
        return entityDO;
    }

    private static IEmployeeAddressService getBean() {
        return SpringBeanUtil.getBean(IEmployeeAddressService.class);
    }

}
